package edu.pitt.dbmi.monarch.rest;

import owltools.cli.Sim2CommandRunner;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Properties;

/**
 * Author : Jeremy Espino MD
 * Created  8/14/13 11:25 AM
 */
public class SimSearch implements Runnable {

    private String runid;
    private Float minimumMaxIC;
    private Float minimumSimJ;
    private ScoringMetrics[] scoringMetrics;
    private OutputFormat outputFormat;
    private String[] compare;
    private String[] instances1;
    private String[] labels1;
    private String[] instances2;
    private String[] labels2;
    private String outputFileName;

    private long startTime;

    public enum OutputFormat {
        JSON,
        TXT;
    }

    public enum ScoringMetrics {
        SIMJ,
        IC_MCS,
        MAXIC,
        JACCARD,
        GIC;
    }

    Sim2CommandRunner runner;

    public String getOutputFileName() {
        return outputFileName;
    }

    public long getStartTime() {
        return startTime;
    }


    public void init(String runid, Float minimumMaxIC, Float minimumSimJ, ScoringMetrics[] scoringMetrics,
                       OutputFormat outputFormat, String[] compare, String[] instances1, String[] labels1,
                       String[] instances2, String[] labels2) {
        runner = new Sim2CommandRunner();
        this.runid = runid;
        this.minimumMaxIC = minimumMaxIC;
        this.minimumSimJ = minimumSimJ;
        this.scoringMetrics = scoringMetrics;
        this.outputFormat = outputFormat;
        this.compare = compare;
        this.instances1 = instances1;
        this.labels1 = labels1;
        this.instances2 = instances2;
        this.labels2 = labels2;

    }

    public void run() {

        startTime = System.currentTimeMillis();

        try {

            if (minimumMaxIC == null) minimumMaxIC = 0.05f;
            if (minimumSimJ == null) minimumSimJ = 0.05f;
            if (scoringMetrics == null) {
                scoringMetrics = new ScoringMetrics[2];
                scoringMetrics[0] = ScoringMetrics.SIMJ;
                scoringMetrics[1] = ScoringMetrics.MAXIC;
            }
            if (outputFormat == null) outputFormat = OutputFormat.JSON;
            if (compare == null) {
                compare = new String[2];
                compare[0] = "OMIM";
                compare[1] = "MGI";
            }

            String runBaseFileName = Env.getInstance().getProperty(Env.WORK_DIRECTORY_PROPERTY) + "/" + runid;
            String propertiesFile = runBaseFileName + ".properties";
            String instanceFileName1 = runBaseFileName + ".if1.tab";
            String labelFileName1 = runBaseFileName + ".lf1.tab";
            String instanceFileName2 = runBaseFileName + ".if2.tab";
            String labelFileName2 = runBaseFileName + ".lf2.tab";
            outputFileName = runBaseFileName + ".out";


            // generate properties file for this run
            Properties p = new Properties();
            p.setProperty("minimumMaxIC", minimumMaxIC.toString());
            p.setProperty("minimumSimJ", minimumSimJ.toString());
            p.setProperty("outputFormat", outputFormat.toString());
            p.setProperty("compare", "OMIM,MGI");
            p.setProperty("scoringMetrics", "SIMJ");
            File f = new File(propertiesFile);
            OutputStream out = new FileOutputStream(f);
            p.store(out, "Automatically generated properties file for runid " + runid);
            out.flush();
            out.close();

            // generate instances file 1
            writeArrayToFile(instanceFileName1, instances1);
            writeArrayToFile(labelFileName1, labels1);
            // generate instances file 2
            writeArrayToFile(instanceFileName2, instances2);
            writeArrayToFile(labelFileName2, labels2);

            // execute the analysis
            runIteration(Env.getInstance().getProperty(Env.ONTOLOGY));
            runIteration("--load-instances " + instanceFileName1);
            runIteration("--load-labels " + labelFileName1);
            runIteration("--load-instances " + instanceFileName2);
            runIteration("--load-labels " + labelFileName2);
            runIteration("--sim-load-lcs-cache " + Env.getInstance().getProperty(Env.DX_MOUSE_CACHE) + " --sim-basic -p " + propertiesFile + " -o " + outputFileName);


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void writeArrayToFile(String filename, String[] array) throws Exception {

        PrintWriter writer = new PrintWriter(filename);
        for (int i = 0; i < array.length; i = i + 2) {
            writer.println(array[i] + "\t" + array[i + 1]);
        }
        writer.flush();
        writer.close();
    }


    public void runIteration(String argStr) throws Exception {
        runner.runSingleIteration(argStr.split(" "));
    }

}
